package com.like.likeutils.network.ud;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.xutils.x;
import org.xutils.common.Callback.CommonCallback;
import org.xutils.http.RequestParams;

public class UploadManager {

    private List<UploadInfo> mAllTasks;
    private List<UploadInfo> mSuccessTasks;
    private List<UploadInfo> mErrorTasks;
    private int mUploadFinishedCount = 0;

    private UploadListener mListener;
    private boolean mIsUploading = false;

    private UploadManager() {
        mSuccessTasks = new ArrayList<>();
        mErrorTasks = new ArrayList<>();
        mAllTasks = new ArrayList<>();
    }

    public static UploadManager newInstance() {
        return new UploadManager();
    }

    public void addUploadInfo(UploadInfo uploadInfo) {
        mAllTasks.add(uploadInfo);
    }

    public void setUploadListener(UploadListener listener) {
        this.mListener = listener;
    }

    public UploadInfo getUploadInfo() {
        return new UploadInfo();
    }

    public UploadInfo getUploadInfo(String url) {
        return new UploadInfo(url);
    }

    public UploadInfo getUploadInfo(String url, Object tag) {
        return new UploadInfo(url, tag);
    }

    public boolean hasTasks() {
        return !(mAllTasks.size() == 0);
    }

    public void start() {
        if (mIsUploading)
            return;
        mIsUploading = true;
        if (mAllTasks.size() == 0) {
            if (mListener != null)
                mListener.onAllFinished(mSuccessTasks, mErrorTasks,
                        mErrorTasks.size() == 0);
            finish();
        }
        for (int i = 0; i < mAllTasks.size(); i++) {
            final UploadInfo uploadInfo = mAllTasks.get(i);
            final int allCount = mAllTasks.size();
            final int finalI = i;
            ProgressListener progressListener = new ProgressListener() {
                @Override
                public void onSuccess(String result) {
                    uploadInfo.result = result;
                    mSuccessTasks.add(uploadInfo);
                }

                @Override
                public void onError(Throwable ex, boolean isOnCallback) {
                    uploadInfo.ex = ex;
                    mErrorTasks.add(uploadInfo);
                }

                @Override
                public void onFinished() {
                    mUploadFinishedCount += 1;
                    if (mUploadFinishedCount == allCount) {
                        if (mListener != null) {
                            mListener.onAllFinished(mSuccessTasks, mErrorTasks,
                                    mErrorTasks.size() == 0);
                        }
                        finish();
                    }
                }

                @Override
                public void onLoading(long total, long current,
                                      boolean isDownload) {
                    if (mListener != null)
                        mListener.onLoading(finalI, allCount, total, current);
                }
            };
            upload(uploadInfo.headers, uploadInfo.url, progressListener,
                    uploadInfo.params);
        }
    }

    private void finish() {
        this.mUploadFinishedCount = 0;
        this.mSuccessTasks.clear();
        this.mErrorTasks.clear();
        this.mAllTasks.clear();
        this.mIsUploading = false;
    }

    public void cancelAll() {
        finish();
    }

    public class UploadInfo {

        public Object tag;
        public String result;
        public Throwable ex;
        public String url;
        public Map<String, Object> params;
        public Map<String, String> headers;

        public UploadInfo() {
            params = new HashMap<String, Object>();
            headers = new HashMap<String, String>();
            this.tag = "";
        }

        public UploadInfo(String url) {
            this();
            this.url = url;
        }

        public UploadInfo(String url, Object tag) {
            this(url);
            this.tag = tag;
        }

        public UploadInfo setUrl(String url) {
            this.url = url;
            return this;
        }

        public UploadInfo addParam(String key, Object param) {
            params.put(key, param);
            return this;
        }

        public UploadInfo addReqHeader(String key, String value) {
            headers.put(key, value);
            return this;
        }

    }

    public void upload(Map<String, String> headers, String url,
                       CommonCallback<String> callBack, Map<String, Object> params) {
        RequestParams requestParams = new RequestParams(url);
        requestParams.setMultipart(true);
        if (headers != null) {
            for (String key : headers.keySet())
                requestParams.addHeader(key, headers.get(key));
        }
        for (String key : params.keySet()) {
            if (params.get(key) instanceof File)
                requestParams.addBodyParameter(key, (File) params.get(key));
            else
                requestParams.addBodyParameter(key, (String) params.get(key));
        }
        x.http().post(requestParams, callBack);
    }

}
